
// MultiPlayerTag_Server
//
//

//  created by PA, April 16, 2013 (derived from Processing SharedCanvasServer/Client example)
//                                    Shared Drawing Canvas (Server) by Alexander R. Galloway. 
//                                    A server that shares a drawing canvas between two computers. 
// modified by PA, April 26, 2013 (server parse and draw of muliple client messages)
// modified by PA, April 30, 2013 (client gets server message, drows other players)
// modified by PA,   May 21, 2013 (more general messaging format)

import processing.net.*;

Server serverThis;
Client aclient; // so we know who sent a message
String input;
float data[];

CPlayer player1;
CPlayer player2;

String type;

ArrayList listPlayers = new ArrayList();

int nNextID = 1000;

void setup() 
{
    size(450, 255);
    background(204);
    stroke(0);
    frameRate(30); // Slow it down a little

    serverThis = new Server( this, 12345 ); // Start a simple server on a port

    //  player1 = new CPlayer( false, 1234 );
    //  player2 = new CPlayer( false, 4321 );
}

// Game loop;
void draw() 
{
    background(222);

    // Check for and process message from a client.
    aclient = serverThis.available();
    if ( aclient != null ) {
        process_message( aclient.readString() );
    }

    // Draw all players.
    for ( int i = 0; i < listPlayers.size(); i++ ) {

        // get a player from the list of players, cast as a player, 
        // then call that players draw function
//        CPlayer player_temp = (CPlayer)listPlayers.get(i);
//        player_temp.draw();
        
        ( (CPlayer) listPlayers.get(i) ).draw();
    }
}

void process_message( String input ) {

    // 'POS', 'FETCH', 'JOIN'
    
    
    // Sanity check:
    // All messages must contain a newline character '\n'.
    if ( input.indexOf("\n") == -1 ) {

        println( "bad client message, no newline:  " + input );
        return;
    }

    input = input.substring( 0, input.indexOf("\n") ); // Only up to the newline

    // Parse message header (space separated) and message body (comma separated).
    // See Jacobs language specification on teletag wiki (Google Code) for details.
    String[] strMsgHeader = split( input, ' ' ); 
    // Parse message into array.
// To Do: Sanity check for at least one comma of the body,
//        where the body is the 4th element of the header


    // Check that first part of message is one of our function words; POS, FETCH, JOIN, etc.
    if (   !strMsgHeader[0].equals( "POS" ) 
        && !strMsgHeader[0].equals( "FETCH" )
        && !strMsgHeader[0].equals( "JOIN" ) ) {
            return;
    }

    // If there's no comma, there's only one part of the body.
// To Do: Make a test message to make sure this works; a message with only one body parameter.

    String[] strMsgBody;
    if ( match( input, "," ) == null ) {
        
        // Either bad message 
        //OR
        // The last part is the full body of the message.
        strMsgBody = new String[1];
        strMsgBody[0] = strMsgHeader[3];
    }
    else{
        strMsgBody = split( strMsgHeader[3], ',' );
    } 
 


    // Sanity check:
    // All messages must start with a valid command: 'POS', 'FETCH', 'JOIN'
    int iCommand = -1;
    if ( strMsgHeader[0].equals( "POS"    ) ){ iCommand = 1; }
    if ( strMsgHeader[0].equals( "FETCH"  ) ){ iCommand = 2; }
    if ( strMsgHeader[0].equals( "JOIN" ) ){ iCommand = 3; }
    
    switch ( iCommand ) {
        
        case 1:
        case 2:
        case 3:
            break;
            
        default:
            println( "bad client message, no newline:  " + input );
            return;
    }       
        
    println( input + "\nis message server heard\n" );
    println( "\n" );






    int nSenderID = int( strMsgHeader[1] ); //sender


    // Process a fetch command.
    if ( strMsgHeader[0].equals( "FETCH" ) ) {

        // add to list of players
        // send a unique ID back to client
        sendJOIN ( strMsgBody[0]  );
        
        // Notify all clients that a new client has joined.
    }

    // Process position command.
    if ( strMsgHeader[0].equals( "POS" ) ) {

        // who is this on list, and update their position.
        CPlayer thisPlayer = getPlayerFromID( listPlayers, nSenderID );
 println("sender ID:" + nSenderID);       
        if ( thisPlayer != null ) {
            thisPlayer.pos.x = float( strMsgBody[0] );
            thisPlayer.pos.y = float( strMsgBody[1] );
        }
         
        // Broadcast every position message back to all clients, verbatim.
        serverThis.write( input + "\n" );
   }

}

CPlayer getPlayerFromID( ArrayList listOfPlayers, int IDtoFind ) {
    
    for ( int i = 0; i < listOfPlayers.size(); i++ ) {
   
        CPlayer thisPlayer = ( (CPlayer) listOfPlayers.get(i) );
        
        if ( thisPlayer.nID == IDtoFind ) {
            
            return thisPlayer;
        }
    }
    
    return null;
}


void sendJOIN ( String strName ) {

    // Assign a unique ID.
    nNextID++;
    
  // Avoid name conflict
   for ( int i = 0; i < listPlayers.size(); i++ ) {
       
        CPlayer thisPlayer = ( (CPlayer) listPlayers.get(i) );
        
        if ( thisPlayer.strName.equals( strName ) ) {
            strName += str(nNextID);
        }
   }
   
    
    type = "JOIN";
    serverThis.write(       type +
        " " + str( 00002 ) +
        " " + str( 00000  ) +
        " " + strName + "," + str(nNextID) + "\n" );


    // Add new player to ArrayList of players.

    listPlayers.add( new CPlayer( false, nNextID, strName ) );
}


